package top.zerocn.dao;

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import top.zerocn.entity.Book;
import top.zerocn.util.ObjectAppendInputStream;
import top.zerocn.util.ObjectAppendOutputStream;

public class BookOperator {

	private static File bookFile;
	private static List<Book> books = new ArrayList<>();

	static {
		// 获取文件
		bookFile = new File(BookOperator.class.getResource("book.data").getFile().replace("%20", " "));
		// 读取文件
		/* 发生错误：
		 * 由于用 FileInputStream(文件名，true) 向同一个文件中序列化对象，每次都会向文件中序列化一个 header。 
		 * 在反序列化的时候每个 ObjectInputStream 对象只会读取一个 header 
		 * 那么当遇到第二个的时候就会报错，导致出现 invalid type code: AC 异常
		 * 所以要么在循环中每次都创建一个新的 ObjectInputStream 用来读取 header，要么不读取 header
		 */
		try (ObjectAppendInputStream objectInputStream = new ObjectAppendInputStream(new FileInputStream(bookFile))) {
			do {
				try {
					Book book = (Book) objectInputStream.readObject();
					books.add(book);
				} catch (EOFException e) {
					// 读到文件末尾时跳出循环
					break;
				} catch (NullPointerException e) {
					// 跳过读取的空对象
					continue;
				}
			} while (true);

		} catch (FileNotFoundException e) {
			System.err.println("未找到book.data文件\n" + e.getMessage());
		} catch (IOException e) {
			System.err.println("读取book.data文件出错\n" + e.getMessage());
		} catch (ClassNotFoundException e) {
			System.err.println("未能读取Book对象\n" + e.getMessage());
		}
	}

	/**
	 * 
	 * @param book
	 * @return
	 */
	public boolean saveBook(Book book) {
		// 存入 List
		books.add(book);
		// 写入文件
		/* 发生错误：
		 * 由于用 FileInputStream(文件名，true) 向同一个文件中序列化对象，每次都会向文件中序列化一个 header
		 * 在反序列化的时候每个 ObjectInputStream 对象只会读取一个 header 
		 * 那么当遇到第二个的时候就会报错，导致出现 invalid type code: AC 异常
		 * 所以重写 ObjectOutputSream 的 writeStreamHeader() 方法，使其不写入头部信息
		 */
		try (ObjectAppendOutputStream objectOutputStream = new ObjectAppendOutputStream(
				new FileOutputStream(bookFile, true))) {
			objectOutputStream.writeObject(book);
			objectOutputStream.flush();
			return true;
		} catch (FileNotFoundException e) {
			System.err.println("未找到book.data文件\n" + e.getMessage());
			return false;
		} catch (IOException e) {
			System.err.println("写入文件出错\n" + e.getMessage());
			return false;
		}

	}

	/**
	 * 
	 * @param name
	 * @return
	 */
	public Book getBook(String name) {
		for (Book book : books) {
			if (Objects.equals(name, book.getName())) {
				return book;
			}
		}
		return null;
	}
}
